#include "FunctionCallRecord.h"

namespace MockItNow
{

FunctionCallRecord::FunctionCallRecord(const FunctionInfo* functionInfo, void* recordTarget, int numArguments)
: next(0),
  m_functionInfo(functionInfo),
  m_recordTarget(recordTarget),
  m_failWhenCalled(false),
  m_returnAlways(false),
  m_ignoreAllArguments(false),
  m_ignoreTarget(false),
  m_recordIndex(0),
  m_replayIndex(0),
  m_argumentRecords(0),
  m_argumentReturnRecords(0),
  m_numArgumentRecords(numArguments),
  m_returnValueRecord(0),
  m_exceptionRecord(0),
  m_callOriginal(false)
{
	if (numArguments > 0)
	{
		m_argumentRecords = new ArgumentRecordInterface*[numArguments];
		m_argumentReturnRecords = new ReturnValueRecordInterface*[numArguments];

		for (int i = 0; i < m_numArgumentRecords; ++i)
		{
			m_argumentRecords[i] = 0;
			m_argumentReturnRecords[i] = 0;
		}
	}
}

FunctionCallRecord::~FunctionCallRecord()
{
	for (int i = 0; i < m_numArgumentRecords; ++i)
	{
		delete m_argumentRecords[i];
		delete m_argumentReturnRecords[i];
	}

	delete[] m_argumentRecords;
	delete[] m_argumentReturnRecords;

	delete m_returnValueRecord;
}

void FunctionCallRecord::IgnoreArgument(int index)
{
	MOCKITNOW_ASSERT(index < m_numArgumentRecords);
	MOCKITNOW_ASSERT(m_argumentRecords[index] != 0);

	m_argumentRecords[index]->IgnoreArgument();
}

void FunctionCallRecord::IgnoreArguments()
{
	m_ignoreAllArguments = true;
}

void FunctionCallRecord::SetFailWhenCalled()
{
	m_failWhenCalled = true;
}

void FunctionCallRecord::SetReturnAlways()
{
	m_returnAlways = true;
}

void FunctionCallRecord::SetIgnoreTarget()
{
	m_ignoreTarget = true;
}

void FunctionCallRecord::CallOriginal()
{
	m_callOriginal = true;
}

void FunctionCallRecord::Verify()
{
	// If we were set to fail when called and we actually
	// got to the verify without triggering a failure then
	// that means we were never called. So all is well.
	if (m_failWhenCalled == true)
		return;

	if (m_ignoreAllArguments == true)
		return;

	if (m_callOriginal == true)
		return;

	for (int i = 0; i < m_numArgumentRecords; ++i)
		m_reportedFailure += m_argumentRecords[i]->Evaluate();
}

size_t FunctionCallRecord::GetFunctionAddress() const
{
	MOCKITNOW_ASSERT(m_functionInfo != 0);
	return m_functionInfo->mockFunctionAddress;
}

void* FunctionCallRecord::GetRecordTarget() const
{
	return m_recordTarget;
}

bool FunctionCallRecord::GetFailWhenCalled() const
{
	return m_failWhenCalled;
}

bool FunctionCallRecord::GetReturnAlways() const
{
	return m_returnAlways;
}

bool FunctionCallRecord::GetIgnoreTarget() const
{
	return m_ignoreTarget;
}

bool FunctionCallRecord::GetCallOriginal() const
{
	return m_callOriginal;
}

int FunctionCallRecord::GetNumArguments() const
{
	return m_numArgumentRecords;
}

bool FunctionCallRecord::HasReturnValue() const
{
	return m_returnValueRecord != 0;
}

const FunctionInfo* FunctionCallRecord::GetFunctionInfo() const
{
	return m_functionInfo;
}

const std::string& FunctionCallRecord::GetReportedFailure() const
{
	return m_reportedFailure;
}

}
